"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
exports.__esModule = true;
var const_1 = require("./common/const");
var express_1 = require("express");
var FakeFactory = /** @class */ (function () {
    function FakeFactory() {
        // 实例化Express
        this.app = (0, express_1["default"])();
        // types将缓存所有Provider，保证其只被实例化一次
        this.types = {};
    }
    // 调用该方法以注册所需信息至Express实例并返回
    FakeFactory.prototype.create = function (module) {
        // 获取在module装饰器中定义的Controller数组
        var Controllers = Reflect.getMetadata("controllers", module);
        this.initControllers(Controllers);
        // 返回Express实例
        return this.app;
    };
    // 初始化所有Controllers
    FakeFactory.prototype.initControllers = function (Controllers) {
        var _this = this;
        Controllers.forEach(function (Controller) {
            // module中的controller数组中每个controller的构造函数的参数的类型
            var paramTypes = Reflect.getMetadata("design:paramtypes", Controller);
            var args = paramTypes.map(function (Type) {
                // 根据Controller构造函数中依赖的参数进行遍历
                // 如果他所依赖的那个参数不是可以Injectable的则直接报错
                // 否则从缓存中拿去这个依赖的实例，如果没有则创建
                if (!Reflect.getMetadata(const_1.FAKE_INJECTABLE_WATERMARK, Type)) {
                    throw new Error("".concat(Type.name, " is not injectable!"));
                }
                else {
                    return _this.types[Type.name] ? _this.types[Type.name] : _this.types[Type.name] = new Type();
                }
            });
            // 根据创建出来的依赖建立一个Controller的实例
            var controller = new (Controller.bind.apply(Controller, __spreadArray([void 0], args, false)))();
            // 获取Controller的路由根路径
            var path = Reflect.getMetadata(const_1.FAKE_BASE_PATH, Controller);
            _this.initRoute(controller, path);
        });
    };
    // 初始化一个controller实例上所有的监听方法
    FakeFactory.prototype.initRoute = function (controller, basePath) {
        var _this = this;
        var proto = Object.getPrototypeOf(controller);
        if (!proto)
            return;
        var methodsNames = Object.getOwnPropertyNames(proto).filter(function (item) {
            return item !== "constructor" && typeof proto[item] === "function";
        });
        methodsNames.forEach(function (methodName) {
            var fn = proto[methodName];
            var methods = Reflect.getMetadata(const_1.FAKE_METHOD, controller, methodName);
            var path = Reflect.getMetadata(const_1.FAKE_PATH, controller, methodName);
            if (!methods || !path)
                return;
            var route = {
                path: basePath + path,
                method: methods.toLowerCase(),
                fn: fn.bind(controller)
            };
            _this.registerRoute(route);
        });
    };
    // 将Http监听方法注册至Express实例之中
    FakeFactory.prototype.registerRoute = function (route) {
        var path = route.path, method = route.method, fn = route.fn;
        // Express实例上注册路由
        // @ts-ignore
        this.app[method](path, function (req, res) {
            res.send(fn(req));
        });
    };
    return FakeFactory;
}());
exports["default"] = new FakeFactory();
